/*
 * Universidad del Valle de Guatemala
 * Algoritmos y Estructura de Datos
 * 
 */
package Calculadora;
/**
 * Referencia para StringTokenizer: http://docs.oracle.com/javase/1.4.2/docs/api/java/util/StringTokenizer.html
 * Referenica para DecimalFormat:   http://chuwiki.chuidiang.org/index.php?title=DecimalFormat 
 */
import Calculadora.Stack.StackVector;
import Calculadora.Stack.Stack;
import Calculadora.Stack.StackList.SinglyLinkedList;
import Calculadora.Stack.StackList.DoublyLinkedList;
import Calculadora.Stack.StackArrayList;
import Calculadora.Stack.StackList.CircularList;
import java.text.DecimalFormat;
import java.util.StringTokenizer;
import javax.swing.JOptionPane;

/**
 *
 * @author Douglas Dávila - 11042
 */
public class Calcu extends javax.swing.JFrame {

    /**
     *
     */
    public Calcu() {
        initComponents();
        contador = 0;           //  control para apagar/encender la calculadora
        mensaje = "";           //  se inicializa el mensaje que se segmentara
        resultado = 0f;          //  resultado temporal para operaciones
        total = 0f;              //  resultado total despues de la expresión PostFix
        cadena = "VE";
        unico = new StackSingletonFactory<Float>();
        /**
         * se crea un objeto de la clase DecimalFormat que tomara un valor 
         * de tipo float y darle un formato de dos decimales
         */
        round = new DecimalFormat("0.##"); 
        /**
         * se crea un objeto de la calse StackVector que usara genericos 
         * de tipo entero, e implementa la interface Stack 
         */
}
    /**
     * Método SegmentarOperar
     * @param cadena
     * @return 
     * Pre: Recibe un String cómo parametro, el cual lo segmenta 
     * POst:    si el String posee números enteros los almacena en la pila del Vector
     *          si tiene operadores realiza los cálculos y retorna el total de tipo entero
     * Condiciones:
     *          si el String es vacio, despliga ventana con mensaje de error
     *          si el String no contiene caractares operables, muestra ventana de error
     */
    public float SegmentarOperar(String cadena){
        
        /**
         * Se crea un objeto de la clase importada StringTokenizar
         * que recibe como parametro un String el cual será segmentado 
         */
        st = new StringTokenizer(cadena);   
               
        while (st.hasMoreTokens()) {
            String caracter = st.nextToken();
            
            //Refencia tomada en: http://www.leepoint.net/notes-java/data/strings/conversion/string2num.html
            try {
                float numero = Float.parseFloat(caracter);
                vector.push(numero);     //si el caracter es entero lo mete a la pila
                
            }catch (NumberFormatException nx) {
                
                    /**
                     * Condiciones para saber que operación se realizará según el operador
                     * los resultados temporales se guardan en la pila del Vector
                     */     
                    if ("+".equals(caracter)) {
                        
                        float dato1 = vector.pop();
                        float dato2 = vector.pop();
                        
                        resultado = (dato1+dato2);
                            
                        vector.push(resultado);
                    
                    } else if ("-".equals(caracter)) {
                        
                        float dato1 = vector.pop();
                        float dato2 = vector.pop();
                        
                        resultado = (-dato1 + dato2);
                        vector.push(resultado);
                        
                    } else if ("*".equals(caracter)) {
                        
                       float dato1 = vector.pop();
                        float dato2 = vector.pop();
                        
                        resultado = (dato1*dato2);
                        vector.push(resultado);
                
                    } else if ("/".equals(caracter)) {
                        
                       float dato1 = vector.pop();
                        float dato2 = vector.pop();
                        
                        resultado = (dato2/dato1);
                        vector.push(resultado);
                    } else {

                        JOptionPane.showMessageDialog(null, "No ingreso una expresion correcta");
                        return 0;
                        }

                    }
                }
        
        //defensiva para cuando la pila del Vector esta vacia.
        
        if (vector.isEmpty()== false) {
        return vector.pop();
        }else {
            JOptionPane.showMessageDialog(null, "Ingrese una expresion");
            return 0;
        }
        }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        Encender = new javax.swing.JButton();
        Entrada = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        Calcular = new javax.swing.JButton();
        jLabel7 = new javax.swing.JLabel();
        display = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        limpiar = new javax.swing.JButton();
        vec = new javax.swing.JRadioButton();
        list = new javax.swing.JRadioButton();
        slist = new javax.swing.JRadioButton();
        dlist = new javax.swing.JRadioButton();
        clist = new javax.swing.JRadioButton();
        jLabel8 = new javax.swing.JLabel();
        aceptar = new javax.swing.JButton();
        jLabel9 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        Encender.setText("Click to On");
        Encender.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                EncenderActionPerformed(evt);
            }
        });

        Entrada.setEnabled(false);
        Entrada.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                EntradaActionPerformed(evt);
            }
        });

        jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        jLabel1.setText("Instrucciones:");
        jLabel1.setEnabled(false);

        jLabel2.setText("2. Ingrese una expresión en formato postfix.");
        jLabel2.setEnabled(false);

        jLabel3.setText("3. Pulse el boton \"Calcular\" para ver el resultado de su expresión");
        jLabel3.setEnabled(false);

        jLabel4.setFont(new java.awt.Font("Tahoma", 2, 11)); // NOI18N
        jLabel4.setText("Nota: Deje un espacion en blanco entre cada número u operador. ");
        jLabel4.setEnabled(false);

        jLabel5.setText("Ingrese acá su expresión Postfix: ");
        jLabel5.setEnabled(false);

        jLabel6.setText("Ejemplo: ((1+3)*4)+3 = 1 3 + 4 * 3 +");
        jLabel6.setEnabled(false);

        Calcular.setText("Calcular");
        Calcular.setEnabled(false);
        Calcular.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CalcularActionPerformed(evt);
            }
        });

        jLabel7.setText("RESULTADO:");
        jLabel7.setEnabled(false);

        display.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N
        display.setText("- - -");
        display.setEnabled(false);

        limpiar.setText("Limpiar");
        limpiar.setEnabled(false);
        limpiar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                limpiarActionPerformed(evt);
            }
        });

        vec.setSelected(true);
        vec.setText("Vector");
        vec.setEnabled(false);
        vec.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                vecActionPerformed(evt);
            }
        });

        list.setText("Lista");
        list.setEnabled(false);
        list.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                listActionPerformed(evt);
            }
        });

        slist.setText("Lista Simple");
        slist.setEnabled(false);
        slist.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                slistActionPerformed(evt);
            }
        });

        dlist.setText("Lista de Doble Enlace");
        dlist.setEnabled(false);
        dlist.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dlistActionPerformed(evt);
            }
        });

        clist.setText("Lista Circular");
        clist.setEnabled(false);
        clist.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clistActionPerformed(evt);
            }
        });

        jLabel8.setText("1. Elija como se manejaran sus datos: ");
        jLabel8.setEnabled(false);

        aceptar.setText("Aceptar");
        aceptar.setEnabled(false);
        aceptar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aceptarActionPerformed(evt);
            }
        });

        jLabel9.setFont(new java.awt.Font("Tahoma", 1, 18)); // NOI18N
        jLabel9.setText("Calculadora");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addGap(10, 10, 10)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel3)
                            .addComponent(jLabel2)
                            .addComponent(jSeparator1)))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel1)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel5)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(Entrada, javax.swing.GroupLayout.PREFERRED_SIZE, 201, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(layout.createSequentialGroup()
                                .addGap(35, 35, 35)
                                .addComponent(jLabel4))
                            .addGroup(layout.createSequentialGroup()
                                .addGap(74, 74, 74)
                                .addComponent(jLabel6))
                            .addGroup(layout.createSequentialGroup()
                                .addGap(10, 10, 10)
                                .addComponent(jLabel8))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(limpiar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(Calcular, javax.swing.GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE))
                                .addGap(41, 41, 41)
                                .addComponent(jLabel7)
                                .addGap(55, 55, 55)
                                .addComponent(display))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(vec)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(list)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(slist)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(dlist)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(aceptar)
                                    .addComponent(clist))))
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(jLabel9)
                        .addGap(74, 74, 74)
                        .addComponent(Encender)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(Encender)
                    .addComponent(jLabel9))
                .addGap(18, 18, 18)
                .addComponent(jLabel1)
                .addGap(7, 7, 7)
                .addComponent(jLabel8)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(vec)
                    .addComponent(list)
                    .addComponent(slist)
                    .addComponent(dlist)
                    .addComponent(clist))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(aceptar)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel6)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel3)
                .addGap(10, 10, 10)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(Entrada, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(9, 9, 9)
                .addComponent(jLabel4)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel7)
                            .addComponent(display))
                        .addGap(21, 21, 21))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(Calcular)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(limpiar)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void CalcularActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CalcularActionPerformed
        /**
         * 
         * Pre: calculadora debe estar modo On
         * post: obtiene la cadena ingresada por el usuario
         *       dicha cadena la asigna cómo parametro al Método SegmentarOperar
         *       el valor retornado es mostrado en Ventana
         */
        
        mensaje = Entrada.getText(); 
        
        vector = unico.getStack(cadena);
        total = SegmentarOperar(mensaje);
        
        display.setText(round.format(total));
        resultado = 0;  //reinicia el resultado temporal 
    }//GEN-LAST:event_CalcularActionPerformed

    private void EntradaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_EntradaActionPerformed
        
    }//GEN-LAST:event_EntradaActionPerformed

    private void EncenderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_EncenderActionPerformed
        contador ++; 
        if (contador == 1){
            aceptar.setEnabled(true);
            vec.setEnabled(true);
            list.setEnabled(true);
            slist.setEnabled(true);
            dlist.setEnabled(true);
            clist.setEnabled(true);
        }
        
        if(contador >1 ){
           Calcular.setEnabled(true);
           limpiar.setEnabled(true);
           Entrada.setEnabled(true);
        }
        if (contador%2==0){
         // se desactivan los componentes cuando se "apague" la calculadora
         Encender.setText("Click to On");
         jLabel1.setEnabled(false);
         jLabel2.setEnabled(false);
         jLabel3.setEnabled(false);
         jLabel4.setEnabled(false);  
         jLabel5.setEnabled(false);
         jLabel6.setEnabled(false);
         jLabel7.setEnabled(false);
         jLabel8.setEnabled(false);
         display.setEnabled(false);
         Calcular.setEnabled(false);
         Entrada.setEnabled(false);
         limpiar.setEnabled(false);
         aceptar.setEnabled(false);
         vec.setEnabled(false);
         list.setEnabled(false);
         slist.setEnabled(false);
         dlist.setEnabled(false);
         clist.setEnabled(false);
         Entrada.setText("");
         display.setText("- - -");
            
        } else {
         //se hacen visbles todos los componentes del panel
         Encender.setText("Click to Off");
         jLabel1.setEnabled(true);
         jLabel2.setEnabled(true);
         jLabel3.setEnabled(true);
         jLabel4.setEnabled(true);  
         jLabel5.setEnabled(true);
         jLabel6.setEnabled(true);
         jLabel7.setEnabled(true);
         jLabel8.setEnabled(true);
         display.setEnabled(true);
         
        }
    }//GEN-LAST:event_EncenderActionPerformed

    private void limpiarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_limpiarActionPerformed
        Entrada.setText("");
        display.setText("- - -");
    }//GEN-LAST:event_limpiarActionPerformed

    private void vecActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_vecActionPerformed
        if(vec.isSelected()== true){
            list.setSelected(false);
            slist.setSelected(false);
            dlist.setSelected(false);
            clist.setSelected(false);
            cadena = "VE";
        }
    }//GEN-LAST:event_vecActionPerformed

    private void listActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_listActionPerformed
        if(list.isSelected()== true){
            vec.setSelected(false);
            slist.setSelected(false);
            dlist.setSelected(false);
            clist.setSelected(false);
            cadena = "AL";
        }
    }//GEN-LAST:event_listActionPerformed

    private void slistActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_slistActionPerformed
        if(slist.isSelected()== true){
            list.setSelected(false);
            vec.setSelected(false);
            dlist.setSelected(false);
            clist.setSelected(false);
            cadena = "SL";
        }
    }//GEN-LAST:event_slistActionPerformed

    private void dlistActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dlistActionPerformed
        if(dlist.isSelected()== true){
            list.setSelected(false);
            slist.setSelected(false);
            vec.setSelected(false);
            clist.setSelected(false);
            cadena = "DL";
        }
    }//GEN-LAST:event_dlistActionPerformed

    private void clistActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clistActionPerformed
        if(clist.isSelected()== true){
            list.setSelected(false);
            slist.setSelected(false);
            dlist.setSelected(false);
            vec.setSelected(false);
            cadena = "CL";
        }
    }//GEN-LAST:event_clistActionPerformed

    private void aceptarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aceptarActionPerformed
         vec.setEnabled(false);
         list.setEnabled(false);
         slist.setEnabled(false);
         dlist.setEnabled(false);
         clist.setEnabled(false);
         Calcular.setEnabled(true);
         limpiar.setEnabled(true);
         Entrada.setEnabled(true);
         aceptar.setEnabled(false);
    }//GEN-LAST:event_aceptarActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Calcu.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Calcu.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Calcu.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Calcu.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Calcu().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton Calcular;
    private javax.swing.JButton Encender;
    private javax.swing.JTextField Entrada;
    private javax.swing.JButton aceptar;
    private javax.swing.JRadioButton clist;
    private javax.swing.JLabel display;
    private javax.swing.JRadioButton dlist;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JButton limpiar;
    private javax.swing.JRadioButton list;
    private javax.swing.JRadioButton slist;
    private javax.swing.JRadioButton vec;
    // End of variables declaration//GEN-END:variables
    // Declaración de Variables   
    int contador;
    String mensaje;
    String cadena;
    Stack<Float> vector;
    StackSingletonFactory<Float> unico;
    StringTokenizer st;
    float resultado; 
    float total;
    DecimalFormat round;
}
